package Server.domain.threads;

import Client.ChatMessage;
import Server.domain.BomberManChatServer;
import Server.domain.BomberManGameServer;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

/**
 *
 * @author Michael Heughebaert <michael.heughebaert.r2449@student.hogent.be>
 */
public class BomberManClientThread extends Thread {

    private BomberManChatServer bmcServer;
    private BomberManGameServer bmgServer;
    private Socket socket;
    private ObjectInputStream iStream;
    private ObjectOutputStream oStream;
    private int clientId;
    private String username;
    private ChatMessage cm;
    private String date;
    private SimpleDateFormat sdf;
    private ArrayList<BomberManClientThread> clients;

    public BomberManClientThread(BomberManChatServer bmcServer, Socket socket, int clientId) {
        this.socket = socket;
        this.bmcServer = bmcServer;
        this.clientId = clientId;
        sdf = new SimpleDateFormat("HH:mm:ss");
        clients = new ArrayList<>();
        System.out.println("Thread trying to create Object Input/Output Streams");
	            try
	            {
	                // create output first
	                oStream = new ObjectOutputStream(socket.getOutputStream());
	                iStream  = new ObjectInputStream(socket.getInputStream());
	                // read the username
	                username = (String) iStream.readObject();
	                bmcServer.display(username + " just connected.");
	            }
	            catch (IOException e) {
	                bmcServer.display("Exception creating new Input/output Streams: " + e);
	                return;
	            }
	            // have to catch ClassNotFoundException
	            // but I read a String, I am sure it will work
	            catch (ClassNotFoundException e) {
	            }
	            date = new Date().toString() + "\n";
    }
    
     public BomberManClientThread(BomberManGameServer bmgServer, Socket socket, int clientId) {
        this.socket = socket;
        this.bmgServer =bmgServer;
        this.clientId = clientId;
        bmgServer.appendEventMessage("Client " + this.clientId + " connected.");
    }
    
    @Override
    public void run() {
    // to loop until LOGOUT
			boolean keepGoing = true;
			while(keepGoing) {
				// read a String (which is an object)
				try {
					cm = (ChatMessage) iStream.readObject();
				}
				catch (IOException e) {
					bmcServer.display(username + " Exception reading Streams: " + e);
					break;				
				}
				catch(ClassNotFoundException e2) {
					break;
				}
				// the messaage part of the ChatMessage
				String message = cm.getMessage();

				// Switch on the type of message receive
				switch(cm.getType()) {

				case ChatMessage.MESSAGE:
					bmcServer.broadcast(username + ": " + message);
					break;
				case ChatMessage.LOGOUT:
					bmcServer.display(username + " disconnected with a LOGOUT message.");
					keepGoing = false;
					break;
				case ChatMessage.WHOISIN:
					writeMsg("List of the users connected at " + sdf.format(new Date()) + "\n");
					// scan al the users connected
					for(int i = 0; i < clients.size(); ++i) {
						BomberManClientThread ct = clients.get(i);
						writeMsg((i+1) + ") " + ct.username + " since " + ct.date);
					}
					break;
				}
			}
			// remove myself from the arrayList containing the list of the
			// connected Clients
			bmcServer.remove(clientId);
			close();
		}

    public void close() {
         // try to close the connection
	            try {
	                if(oStream != null) oStream.close();
	            }
	            catch(Exception e) {}
	            try {
	                if(iStream != null) iStream.close();
	            }
	            catch(Exception e) {};
	            try {
	                if(socket != null) socket.close();
	            }
	            catch (Exception e) {}
	        }
    

    public int getClientId() {
        return clientId;
    }
    
    public String getUsername() {
        return username;
    }
    
    public boolean writeMsg(String msg) {
	            // if Client is still connected send the message to it
	            if(!socket.isConnected()) {
	                close();
	                return false;
	            }
	            // write the message to the stream
	            try {
	                oStream.writeObject(msg);
	            }
	            // if an error occurs, do not abort just inform the user
	            catch(IOException e) {
	                bmcServer.display("Error sending message to " + username);
	                bmcServer.display(e.toString());
	            }
	            return true;
	        }
    
    public Socket getSocket() {
        return socket;
    }

    public ObjectInputStream getiStream() {
        return iStream;
    }

    public ObjectOutputStream getoStream() {
        return oStream;
    }
}